<?php

namespace app\api\controller;
use think\facade\Config;
use app\common\model\User;
use app\Request;
use fast\Http;
use think\facade\Cache;
use think\facade\Db;
use app\common\controller\Api;
use fast\Random;
class Wechat extends Api
{
    protected $noNeedLogin = ['getopenid','registered','wxlogin','getPhoneNumber'];
    protected $userModel = null;
    protected $appId = '';
    protected $appSecret = '';
    protected $redis = null;
    public function initialize(){
        parent::initialize();
        $this->redis =  new \fast\Redis();
        $this -> userModel = new User();
        //获取小程序配置
    }
    public function getopenid(){
        $request = $this->request->request();
        $code = $request['code'];//小程序传来的code值
        $appid = Config::get('site.miniprogram_app_id');//小程序的appid
        $appSecret = Config::get('site.miniprogram_app_secret');// 小程序的$appSecret
        $url = 'https://api.weixin.qq.com/sns/jscode2session';
        $param = [
            'appid' => $appid,
            'secret' => $appSecret,
            'js_code' => $code,
            'grant_type' => 'authorization_code'
        ];
        $result = json_decode(Http::get($url, $param), 1);
        if (empty($result)) {
            $this->error('获取openid时异常，微信内部错误');
        } else {
            $loginFail = array_key_exists('errcode', $result);
            if ($loginFail) {//请求失败
                $this->error('获取失败', $result);
            } else {//请求成功
                $openid = $result['openid'];
                $this->success('获取成功', $result);
            }
        }
    }

    //注册
    public function registered(){
        $request = $this->request->request();
        unset($request['s']);
        Db::startTrans();
        $score = Config::get('site.score') ?? 10;
        $user_op = Db::name('user')->where('openid', $request['openid']) ->find();
        if(!$user_op){
            if (isset($request['shareid']) && !empty($request['shareid'])) {
                $uid = Db::name('user')->where('id', $request['shareid'])->value('id');
                if (!$uid) {
                    Db::rollback();
                    $this->error('邀请码不存在');
                }else{
                    $qscroe =  Db::name('user') -> where('id',$uid) -> value('score');
                    $editupdate = Db::name('user') -> where('id',$uid) -> inc('score',$score) -> update();
                    $hscroe =  (int)$qscroe + $score;
                    if(!$editupdate){
                        Db::rollback();
                        $this->error('健康币变更失败');
                    }
                    $retusl = $this -> scoreadd($uid,$score,$qscroe,$hscroe,"邀请好友注册送".$score."健康币");
                    if(!$retusl){
                        Db::rollback();
                        $this->error('注册失败');
                    }
                }
                $request['shareid'] = $uid;
            }
//            $request['sharecode'] = $this->congsssfu();
            $request['createtime'] = $request['updatetime'] = time();
            $request['status'] = 1;
            $request['loginip'] = get_client_ip();
            $user_add = Db::name('user')->insertGetId($request);
            if (!$user_add) {
                Db::rollback();
                $this->error('用户添加失败');
            }
            $param1 = [
                'gender' => $request['gender'],
                'language' => $request['language'],
                'uid' => $user_add,
            ];
            $userinfo = Db::name('user_info') -> insert($param1);
            if(!$userinfo){
                Db::rollback();
                $this->error('用户添加失败');
            }
        }else{
            unset($request['shareid']);
            $request['updatetime'] = time();
            $user_edit = Db::name('user')->where('openid', $request['openid'])->update($request);
            if (!$user_edit) {
                Db::rollback();
                $this->error('用户信息变更失败');
            }
            $user_add = $user_op['id'];
            $request['shareid'] = $user_op['shareid'];
        }
//
        $token = Random::uuid();
        $this->redis->set($token, $user_add);
        Db::commit();
        $this->success('变更成功', ['token' => $token,'uid'=>$user_add, 'nickname' => $request['nickname'], 'avatar' => $request['avatar'], 'shareid' => $request['shareid']]);

    }

    //生成邀请码
    public function congsssfu($invitationCode = null)
    {
        if ($invitationCode == null) {
            $invitationCode = $this->create_invite_code();
        }
        $cong = Db::name('user')->where('sharecode', $invitationCode)->value('sharecode');
        if ($cong) {
            $this->congsssfu($this->create_invite_code());
        } else {
            return $invitationCode;
        }
    }

    function create_invite_code()
    {
        $code = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $rand = $code[rand(0, 25)]
            . strtoupper(dechex(date('m')))
            . date('d')
            . substr(time(), -5)
            . substr(microtime(), 2, 5)
            . sprintf('%02d', rand(0, 99));
        for (
            $a = md5($rand, true),
            $s = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
            $d = '',
            $f = 0;
            $f < 6;
            $g = ord($a[$f]),
            $d .= $s[($g ^ ord($a[$f + 8])) - $g & 0x1F],
            $f++
        ) ;
        return $d;
    }

    /**
     * 解密手机号
     * @param Request $request
     * @return \think\response\Json
     */
    public function getPhoneNumber(){
        $request = $this->request->request();
        Db::startTrans();
        $data = $this->decryptData($request['encryptedData'], $request['iv'], $request['sessionKey']);
        $mobile = $data['phoneNumber'];
        $user = Db::name('user') -> where('openid', $request['openid']) -> find();
        if(!$user){
            Db::rollback();
            $this->error('用户不存在');
        }
        $data = [
            'updatetime' => time(),
            'mobile' => $mobile
        ];
        Db::name('user') -> where('openid', $request['openid'])  -> update($data);
        Db::commit();
        $this -> success('编辑成功',['mobile'=>$mobile]);
    }


    /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    private function decryptData( $encryptedData, $iv, $sessionKey)
    {
        if (strlen($sessionKey) != 24) {
            return -41001;
        }
        $aesKey=base64_decode($sessionKey);

        if (strlen($iv) != 24) {
            return -41002;
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj=json_decode( $result, 1);

        if( $dataObj  == NULL )
        {
            return -41003;
        }
        if( $dataObj->watermark->appid != $this->appid )
        {
            return -41003;
        }
        return $dataObj;
    }

}